package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.jsonwebtoken.Claims;
import org.example.config.PropertiesConfig;
import org.example.param.UserFuzzyParam;
import org.example.param.UserRegisterParam;
import org.example.domain.User;
import org.example.mapper.UserMapper;
import org.example.param.UserUpdateParam;
import org.example.param.UserUpdatePwdParam;
import org.example.service.UserService;
import org.example.utils.*;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;


    @Override
    public Result findUserById(Long id) {
        User user = userMapper.selectById(id);
        return Result.success(user);
    }

    @Override
    public Result all() {
        List<User> userList = userMapper.selectList(null);
        return Result.success(userList);
    }

    /**
     * 注册
     * @param userRegisterParam
     * @return
     */
    @Override
    @Transactional
    public Result register(UserRegisterParam userRegisterParam) {
        if (findUserByAccount(userRegisterParam.getAccount()).getData()!=null){
            return Result.fail(HttpCode.ACCOUNT_EXIST);
        }
        User user = User.builder().account(userRegisterParam.getAccount())
                .password(MD5Util.encode(userRegisterParam.getPassword()))
                .avatar("")
                .salt(PropertiesConfig.getSalt())
                .admin(0)
                .status("normal")
                .isDelete(0)
                .createDate(System.currentTimeMillis())
                .build();
        int total = userMapper.insert(user);
        if (total == 0){
            return Result.fail(HttpCode.INSERT_ERROR);
        }
        return Result.success();
    }

    /**
     * 删除用户,逻辑删除
     * @param id
     * @return
     */
    public Result delete(Long id){
        int total = userMapper.deleteById(id);
        if (total == 0){
            return Result.fail(HttpCode.DELETE_ERROR);
        }
        return Result.success();
    }

    @Override
    @Transactional
    public Result update(UserUpdateParam userUpdateParam) {
        User user = new User();
        BeanUtils.copyProperties(userUpdateParam,user);
        int total = userMapper.updateById(user);
        if (total == 0){
            return Result.fail(HttpCode.UPDATE_ERROR);
        }
        return Result.success();
    }

    @Override
    @Transactional
    public Result updatePassword(UserUpdatePwdParam userUpdatePwdParam) {
        User data = (User) findUserById(userUpdatePwdParam.getId()).getData();
        if (data == null){
            return Result.fail(HttpCode.ACCOUNT_NO_EXIST);
        }
        if (!MD5Util.matches(userUpdatePwdParam.getOldPassword(),data.getSalt(),data.getPassword())){
            return Result.fail(HttpCode.PASSWORD_ERROR);
        }
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getId,userUpdatePwdParam.getId());

        String newPassword = MD5Util.encode(userUpdatePwdParam.getNewPassword());
        String salt = PropertiesConfig.getSalt();
        User user = User.builder().password(newPassword).salt(salt).build();
        int total = userMapper.update(user, wrapper);
        if (total == 0){
            return Result.fail(HttpCode.UPDATE_ERROR);
        }
        return Result.success();
    }

    @Override
    public Result currentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String token = (String) authentication.getCredentials();
        if (!StringUtils.hasText(token)){
            return Result.fail(HttpCode.NO_LOGIN);
        }
        Claims claims = JwtUtil.decryptToken(token);
        if (claims == null){
            return Result.fail(HttpCode.TOKEN_ERROR);
        }
        Long id = Long.valueOf(claims.getId());
        return findUserById(id);
    }

    @Override
    public Result updateAvatar(String avatar) {
        if (!StringUtils.hasText(avatar)){
            return Result.fail(HttpCode.PARAM_ERROR);
        }
        Long id = SecurityContextUtil.getCurrentUserId();
        User user = User.builder()
                .id(id)
                .avatar(avatar)
                .build();
        int total = userMapper.updateById(user);
        if (total == 0){
            return Result.fail(HttpCode.UPDATE_ERROR);
        }
        return Result.success();
    }


    @Override
    public Result findUserByAccount(String account) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getAccount,account);
        wrapper.last("limit 1");
        User user = userMapper.selectOne(wrapper);
        return Result.success(user);
    }

    @Override
    public Result fuzzy(UserFuzzyParam userFuzzyParam) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        // 模糊查询条件
        wrapper.like(StringUtils.hasText(userFuzzyParam.getAccount()),User::getAccount,userFuzzyParam.getAccount());

        Page page = userMapper.selectPage(
                new Page(userFuzzyParam.getPageNum(), userFuzzyParam.getPageSize()),
                wrapper
        );
        return Result.success(page);
    }

    @Override
    public Result getUserByName(String account) {
        if (!StringUtils.hasText(account)){
            return Result.fail(HttpCode.PARAM_ERROR);
        }
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getAccount,account);
        wrapper.last("limit 1"); //若是重名,只查一个,防止报错
        User user = userMapper.selectOne(wrapper);
        return Result.success(user);
    }

}
